﻿using System;
using System.Collections.Generic;
using System.Linq;
using Best.SmartCms.Dao;
using Best.SmartCms.Domain;
using Best.SmartCms.Dto.Response;
using Best.SmartCms.Dto;
using Best.SmartCms.Service.BizException;
using Best.SmartCms.Service.Common;
using Best.SmartCms.Utility;

namespace Best.SmartCms.Service
{
    /// <summary>
    /// Department服务
    /// </summary>
    public class DepartmentService : IService
    {
        private readonly DepartmentDao _departmentDao;
        private readonly WorkContext _workContext;


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="mySqlDbContext"></param>
        /// <param name="workContext"></param>
        public DepartmentService(MySqlDbContext mySqlDbContext, WorkContext workContext)
        {
            _workContext = workContext;
            _departmentDao = new DepartmentDao(mySqlDbContext);
        }

        

        /// <summary>
        /// 分页列表
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public PagedResponse<DepartmentListDto> PageList(DepartmentListQueryDto query)
        {
            var list = _departmentDao.PageList(query, out var totalCount, out var totalPages);
            var pageList = TinyMapperExtensions.Map<List<Department>, List<DepartmentListDto>>(list);
            foreach (var item in pageList)
            {
                if (item.ParentId > 0)
                {
                    var parentDep = _departmentDao.GetSingle(item.ParentId.GetValueOrDefault());
                    item.ParentDepartmentName = parentDep?.DepartmentName;
                }
            }

            return new PagedResponse<DepartmentListDto>(pageList, query.PageIndex,query.PageSize,totalCount,totalPages);
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="dto"></param>
        public void Create(DepartmentEditDto dto)
        {
            var entity = TinyMapperExtensions.Map<DepartmentEditDto, Department>(dto);
            entity.CreatedTime = DateTime.Now;
            entity.CreatorId = _workContext.UserId;
            entity.CreatorName = _workContext.UserName;
            entity.UpdatorId = _workContext.UserId;
            entity.UpdatorName = _workContext.UserName;
            entity.UpdatedTime = DateTime.Now;
            _departmentDao.Add(entity);
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="dto"></param>
        public void Edit(DepartmentEditDto dto)
        {
            var entity = _departmentDao.GetSingle(dto.Id);
            if (entity == null)
            {
                throw new ParameterNullException($"未找到{dto.Id}的数据");
            }

            // 不能将下级部门作为自己的上级
            if (dto.ParentId > 0 && dto.ParentId != entity.ParentId)
            {
                CheckParentDepartment(dto.Id,dto.ParentId.GetValueOrDefault());
            }

            TinyMapperExtensions.Map(dto, entity);
            
            entity.UpdatorId = _workContext.UserId;
            entity.UpdatorName = _workContext.UserName;
            entity.UpdatedTime = DateTime.Now;

            _departmentDao.Update(entity);
        }

        /// <summary>
        /// 获取所有下级部门逐级
        /// </summary>
        /// <param name="id"></param>
        /// <param name="parentId"></param>
        private void CheckParentDepartment(long id,long parentId)
        {
            if (parentId < 1)
            {
                return;
            }

            var parentDep = _departmentDao.GetSingle(parentId);
            if (parentDep == null)
            {
                return;
            }

            if (id == parentDep.ParentId)
            {
                throw new ParameterValidationException("不能子级部门作为父极部门");
            }

            CheckParentDepartment(id, parentDep.ParentId.GetValueOrDefault());
        }

        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public DepartmentEditDto Info(long id)
        {
            var entity = _departmentDao.GetSingle(id);
            return TinyMapperExtensions.Map<Department, DepartmentEditDto>(entity);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        public void Delete(long id)
        {
            var entity = _departmentDao.GetSingle(id);
            if (entity == null)
            {
                throw new ParameterNullException($"未找到{id}的数据");
            }

            _departmentDao.Delete(entity);
        }

        /// <summary>
        /// 获取部门树结构
        /// </summary>
        /// <returns></returns>
        public List<TreeNodeDto> Tree()
        {
            var treeNodes = new List<TreeNodeDto>();
            var list = _departmentDao.FindAll();
            var parentNodes = list.Where(p => p.ParentId is null || p.ParentId<1).ToList();
            foreach (var item in parentNodes)
            {
                var treeNode = new TreeNodeDto
                {
                    Key = item.Id.ToString(),
                    Title = item.DepartmentName,
                    Children = GetChidren(item, list)
                };

                treeNodes.Add(treeNode);
            }

            return treeNodes;
        }

        /// <summary>
        /// 获取子级数据
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        private List<TreeNodeDto> GetChidren(Department parentNode, List<Department> list)
        {
            var treeNodes = new List<TreeNodeDto>();
            var parentNodes = list.Where(p => p.ParentId== parentNode.Id).ToList();
            if (parentNodes.Count < 1)
            {
                return treeNodes;
            }

            foreach (var item in parentNodes)
            {
                var treeNode = new TreeNodeDto
                {
                    Key = item.Id.ToString(),
                    Title = item.DepartmentName,
                    Children = GetChidren(item, list)
                };

                treeNodes.Add(treeNode);
            }

            return treeNodes;
        }
    }
}
